home *** CD-ROM | disk | FTP | other *** search
- /*
- * ping.c - ping
- *
- * Copyright (C) 1994 Tomoaki Tada/F.C.T.
- */
-
- static char *rcsid = "$Id: ping.c,v 1.7 1994/08/09 04:10:49 Niggle Exp $";
-
- /*
- * $Log: ping.c,v $
- * Revision 1.7 1994/08/09 04:10:49 Niggle
- * enable option -n
- * check damaged packet
- *
- * Revision 1.6 1994/08/04 05:02:08 Niggle
- * inetdé¬ÅφÆôé╡é─éóé╚éóÅΩìçé╠ò\Īé≡ò╧ìX
- *
- * Revision 1.5 1994/08/03 01:57:27 Niggle
- * from addressé≡É│é╡é¡ò\Īé╖éΘéµéñé╔ò╧ìX
- *
- * Revision 1.4 1994/07/28 07:49:19 Niggle
- * no response é╠Ä₧é╠ò\Īé≡ò╧ìX
- *
- * Revision 1.3 1994/07/19 05:16:38 Niggle
- * duplicatesé╔æ╬ë₧
- *
- * Revision 1.2 1994/07/19 03:28:21 Niggle
- * cksumé╠ìéæ¼ë╗
- * usageé╠ò\Ī
- * é╗é╠æ╝éóéδéóéδ
- *
- * Revision 1.1 1994/06/23 03:56:12 Niggle
- * Initial revision
- *
- */
-
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include<time.h>
- #include<signal.h>
- #include<limits.h>
- #ifdef __human68k__
- #undef __DOS_INLINE__
- #define __DOS_INLINE__
- #include<sys/dos.h>
- #endif
-
- #include"network.h"
- #include"socket.h"
- #include"ping.h"
-
- static int send_request (int, long, unsigned short, unsigned short, unsigned short);
- static int doping (long, long, long, long);
- static void ping_recv (void);
- static void ping_send (void);
- static void handler (int);
- static unsigned short eac (long);
- static unsigned short cksum (unsigned char *, unsigned short);
- static void display_ratio (void);
- static volatile void display_usage (void);
- static int isnumstr (const unsigned char *);
- static void check_data (const unsigned char *, int);
-
- static int ping_socket = -1;
- static struct ping ping;
- static int no_convert_p;
-
- static int sending;
- static char *hostname, *ipaddr;
- struct mib_entry *icmp_mib;
-
- /************************************************
- * *
- ************************************************/
- void
- main (int argc, char **argv)
- {
- int i, c;
- long target, interval, count, size;
- struct mib_array *top;
-
- top = get_mib_list ();
- if (!top)
- {
- fprintf (stderr, "TCP/IP driveré═ÅφÆôé╡é─éóé▄é╣é±\n");
- return;
- }
-
- for (i = 0; i < 4; i++)
- {
- if (!strcmp (top[i].name, "ICMP"))
- break;
- }
- if (i < 4)
- icmp_mib = top[i].mib;
- else
- icmp_mib = NULL;
-
- count = -1;
- interval = 1;
- opterr = 1;
- size = 56;
- while ((c = getopt (argc, argv, "c:i:n")) != EOF)
- {
- switch (c)
- {
- case 'c':
- if (!isnumstr (optarg))
- display_usage ();
- count = atol (optarg);
- if (count < 1)
- count = 1;
- break;
- case 'i':
- if (!isnumstr (optarg))
- display_usage ();
- interval = atol (optarg);
- if (interval < 1)
- interval = 1;
- break;
- case 'n':
- no_convert_p = 1;
- break;
- case '?':
- break;
- default:
- break;
- }
- }
-
- if (optind < argc)
- {
- char _ipaddr[64];
-
- if (isipaddr (argv[optind]))
- {
- target = a2n_ipaddr (argv[optind]);
- ipaddr = argv[optind];
- }
- else
- {
- struct hostent *h;
- h = gethostbyname (argv[optind]);
- if (h)
- {
- target = *(long *)h->h_addr;
- ipaddr = n2a_ipaddr (target, _ipaddr);
- }
- else
- {
- ipaddr = NULL;
- target = 0;
- }
- }
- hostname = argv[optind];
-
- if (target)
- {
- signal (SIGINT, handler);
- doping (target, size, interval, count);
- signal (SIGINT, SIG_DFL);
- }
- else
- fprintf (stderr, "ping: host name look up failed\n");
- }
- else
- display_usage ();
-
- return;
- }
-
- /************************************************
- * *
- ************************************************/
- static void
- display_ratio (void)
- {
- double sent, res, avg;
- sent = ping.sent;
- if (sending)
- {
- sent -= 1;
- ping.sent -= 1;
- }
- res = ping.responses;
- avg = res / sent * 100;
- avg = 100.0 - avg;
-
- printf ("\n");
- /* display rate */
- printf ("--- %s ping statistics ---\n", hostname);
- if (ping.dup)
- {
- printf ("%d packets transmitted, %d packets received, +%d duplicates, %.2f%% packet loss\n",
- ping.sent, ping.responses, ping.dup, avg);
- }
- else
- {
- printf ("%d packets transmitted, %d packets received, %.2f%% packet loss\n",
- ping.sent, ping.responses, avg);
- }
- if (ping.responses)
- printf ("round-trip min/avg/max = %d/%.2f/%d ms\n",
- ping.mrtt, (double)ping.srtt / res, ping.Mrtt);
- else
- printf ("round-trip min/avg/max = 0/0/0 ms\n");
- fflush (stdout);
- return;
- }
-
- /************************************************
- * *
- ************************************************/
- static void
- handler (int dummy)
- {
- if (ping_socket)
- close_s (ping_socket);
-
- display_ratio ();
- exit (0);
- }
-
- /************************************************
- * *
- ************************************************/
- static int
- doping (long target, long len, long interval, long count)
- {
- int i;
-
- memset ((char *) &ping, 0, sizeof (ping));
- ping_socket = socket (AF_INET, SOCK_RAW, ICMP_PCTL);
- if (ping_socket == -1)
- return 1;
-
- ping.target = target;
-
- ping.mrtt = LONG_MAX;
- ping.Mrtt = LONG_MIN;
- ping.len = len;
- ping.interval = interval *= CLOCKS_PER_SEC;
-
- printf ("PING %s (%s): %d data bytes\n", hostname, ipaddr, len);
- fflush (stdout);
-
- ping.sent = 0;
- if (count >= 0)
- {
- for (i = 0; i < count; i++)
- {
- clock_t start;
-
- start = clock ();
- sending = 1;
- ping_send ();
-
- while (clock () - start < interval)
- {
- ping_recv ();
- #ifdef __human68k__
- /* check ^C */
- if (_dos_keysns ())
- _dos_getchar ();
- #endif
- }
- ping.lost = ping.sent - ping.responses;
- }
- }
- else
- {
- for (;;)
- {
- clock_t start;
-
- start = clock ();
- sending = 1;
- ping_send ();
-
- while (clock () - start < interval)
- {
- ping_recv ();
- #ifdef __human68k__
- /* check ^C */
- if (_dos_keysns ())
- _dos_getchar ();
- #endif
- }
- sending = 0;
- ping.lost = ping.sent - ping.responses;
- }
- }
-
- close_s (ping_socket); ping_socket = -1;
- display_ratio ();
- return 0;
- }
-
- /************************************************
- * *
- ************************************************/
- static void
- ping_send (void)
- {
- send_request (ping_socket, ping.target, ping.sent++, ping_socket, ping.len);
- }
-
- /************************************************
- * *
- ************************************************/
- static void
- ping_recv (void)
- {
- struct icmp icmp;
- long timestamp, rtt;
- struct sockaddr_in from;
- int fromlen;
- int len;
- int dup_p;
- char buff[2048];
- char _hostname[64];
- clock_t now;
-
- now = clock ();
- fromlen = sizeof (from);
-
- if (!socklen (ping_socket, 0))
- return;
-
- len = recvfrom (ping_socket, buff, ping.len + sizeof (struct icmp),
- 0, (char *) &from, &fromlen);
- if (len == -1)
- return;
-
- sending = 0;
- memcpy (&icmp, buff, sizeof (struct icmp));
- if (icmp.type != ICMP_ECHO_REPLY || icmp.id != ping_socket)
- return;
-
- dup_p = 0;
- if (ping.sent == ping.responses + 1 + ping.lost)
- ping.responses++;
- else
- {
- dup_p = 1;
- ping.dup++;
- }
-
- /* Get stamp */
- memcpy ((char *)×tamp, buff + sizeof (struct icmp), sizeof (timestamp));
-
- {
- struct hostent *h;
- long from_ip;
-
- from_ip = from.sin_addr.s_addr;
- if (!no_convert_p)
- {
- h = gethostbyaddr ((char *)&from_ip, sizeof (long), AF_INET);
- if (h)
- {
- char *dot;
- strcpy (_hostname, h->h_name);
- dot = strchr (_hostname, '.');
- if (dot)
- {
- if (!strcmp (dot + 1, get_domain_name ()))
- *dot = '\0';
- }
- }
- else
- n2a_ipaddr (from_ip, _hostname);
- }
- else
- n2a_ipaddr (from_ip, _hostname);
- }
-
-
- /* Compute round trip time, update smoothed estimates */
- rtt = (now - timestamp) * (1000 / CLOCKS_PER_SEC);
- printf ("%d bytes from %s: icmp_seq=%d time=%d ms",
- len, _hostname, icmp.seq, rtt);
- if (dup_p)
- printf (" (DUP!)\n");
- else
- printf ("\n");
-
- check_data (buff, len - sizeof (struct icmp));
-
- if (ping.mrtt > rtt)
- ping.mrtt = rtt;
- if (ping.Mrtt < rtt)
- ping.Mrtt = rtt;
-
- ping.srtt += rtt;
-
- fflush (stdout);
- }
-
- /************************************************
- * *
- ************************************************/
- static int
- send_request (int s, long target, unsigned short seq, unsigned short id, unsigned short len)
- {
- struct icmp *icmp;
- struct sockaddr_in to;
- char data[2048];
-
- /* Set optional data field, if any, to all 55's */
- if (len != 0)
- {
- char *p;
- int i;
-
- p = data + sizeof (struct icmp);
- for (i = 0; i < len; i++)
- *p++ = (char)i;
- }
-
- /* Insert timestamp and build ICMP header */
- *(clock_t *)(data + sizeof (struct icmp)) = clock ();
- if (icmp_mib)
- {
- icmp_mib[21].value.integer++;
- icmp_mib[14].value.integer++;
- }
-
- icmp = (struct icmp *)&data;
- icmp->type = ICMP_ECHO;
- icmp->code = 0;
- icmp->cksum = 0;
- icmp->seq = seq;
- icmp->id = id;
-
- icmp->cksum = cksum ((unsigned char *)icmp, sizeof (struct icmp) + ping.len);
-
- to.sin_family = AF_INET;
- to.sin_addr.s_addr = target;
- sendto (ping_socket, data, sizeof (struct icmp) + len, 0, (char *) &to, sizeof (to));
- return 0;
- }
-
- /************************************************
- * 16bit é┼ 1é╠òΓÉöé╠ÿaé╠îπÄnûû *
- ************************************************/
- static unsigned short
- eac (long sum)
- {
- unsigned short csum;
-
- while ((csum = sum >> 16) != 0)
- sum = csum + (sum & 0xffff);
-
- return (unsigned short) (sum & 0xffff);
- }
-
- /************************************************
- * *
- ************************************************/
- static unsigned short
- cksum (unsigned char *_m, unsigned short _len)
- {
- long sum;
- int len;
- unsigned short *p;
-
- len = _len >> 1;
- p = (unsigned short *)_m;
- sum = 0;
- while (len-- != 0)
- sum += *p++;
-
- return ~eac (sum) & 0xffff;
- }
-
- /************************************************
- * *
- ************************************************/
- static int
- isnumstr (const unsigned char *target)
- {
- return strspn ((char *)target, "0123456789") == strlen (target);
- }
-
- /************************************************
- * *
- ************************************************/
- static volatile void
- display_usage (void)
- {
- printf ("usage: ping [-c count] [-i interval] host\n");
- exit (0);
- }
-
- /************************************************
- * *
- ************************************************/
- static void
- check_data (const unsigned char *buff, int size)
- {
- const unsigned char *p;
- int i, bad;
-
- bad = 0;
- p = buff + sizeof (struct icmp) + sizeof (clock_t);
- for (i = sizeof (clock_t); i < size; i++, p++)
- {
- int c;
-
- c = *p;
- if (c != i)
- {
- printf ("wrong data byte #%d should be 0x%x was 0x%x\n", i, i, c);
- bad++;
- }
- }
- if (bad)
- {
- for (i = 0, p = buff + sizeof (struct icmp); i < size; i++, p++)
- {
- if (!i)
- printf ("\t");
- else if (!(i % 24))
- printf ("\n\t");
-
- printf ("%2.2x ", *p);
- }
- printf ("\n");
- }
- }
-